#include "stdafx.h"
#include "lfsr.h"

Lfsr::Lfsr(void){}

Lfsr::Lfsr(char* keyPath){

int err = 0, size = 0;
char* registre;
char* retroaction;
string contenu;

	ifstream fichier(keyPath, ios::in);
	if(!fichier){
		cerr << "Erreur à l'ouverture !" << endl;
	}           
	
	//size

	getline(fichier,contenu);
	if(contenu.compare("---------- LENGTH BEGIN ----------") != 0){
		cerr << "Erreur dans le format du fichier de clé !" << endl;
		err = 1;
	}

	getline(fichier,contenu);
	size = atoi(contenu.c_str());

	getline(fichier,contenu);
	if(contenu.compare("---------- LENGTH END ----------") != 0){
		cerr << "Erreur dans le format du fichier de clé !" << endl;
		err = 1;
	}

	//registre

	getline(fichier,contenu);
	if(contenu.compare("---------- REGISTER BEGIN ----------") != 0){
		cerr << "Erreur dans le format du fichier de clé !" << endl;
		err = 1;
	}

	getline(fichier,contenu);
	CREATE(registre, char, size);
	strcpy(registre,(char*)contenu.c_str());

	getline(fichier,contenu);
	if(contenu.compare("---------- REGISTER END ----------") != 0){
		cerr << "Erreur dans le format du fichier de clé !" << endl;
		err = 1;
	}

	//retroaction

	getline(fichier,contenu);
	if(contenu.compare("---------- FEEDBACK BEGIN ----------") != 0){
		cerr << "Erreur dans le format du fichier de clé !" << endl;
		err = 1;
	}

	getline(fichier,contenu);
	CREATE(retroaction, char, size);
	strcpy(retroaction,(char*)contenu.c_str());

	getline(fichier,contenu);
	if(contenu.compare("---------- FEEDBACK END ----------") != 0){
		cerr << "Erreur dans le format du fichier de clé !" << endl;
		err = 1;
	}
	
	fichier.close();
	if(err == 0){
		this->init(size,registre,retroaction);
	}

}

Lfsr::Lfsr(int size, char* init_registre, char* retroaction){
	this->init(size, init_registre, retroaction);
}

int Lfsr::generate_key(char* keyPath, const int keySize){

	if(keySize > 31)	return 1;

srand(time(NULL));
char* registre = CREATE(registre,char,keySize+1);
char* retroaction = CREATE(retroaction,char,keySize+2);
int i;
float number;


	for(i = keySize; i > 0; i--){
		number = (float)rand() / RAND_MAX;
		if(number >= 0.5)	registre[i-1] = '1';
		else	registre[i-1] = '0';

		number = (float)rand() / RAND_MAX;
		if(number >= 0.5)	retroaction[i-1] = '1';
		else	retroaction[i-1] = '0';
	}

	registre[keySize] = 0;
	retroaction[0] = '1';
	retroaction[keySize] = '1';
	retroaction[keySize+1] = 0;

	ofstream fichier(keyPath, ios::out | ios::trunc);
	if(!fichier){
		cerr << "Erreur à l'ouverture !" << endl;
		return 1;
	}
	
	fichier << "---------- LENGTH BEGIN ----------" << endl;
	fichier << keySize << endl;
	fichier << "---------- LENGTH END ----------" << endl;
	fichier << "---------- REGISTER BEGIN ----------" << endl;
	fichier << registre << endl;
	fichier << "---------- REGISTER END ----------" << endl;
	fichier << "---------- FEEDBACK BEGIN ----------" << endl;
	fichier << retroaction << endl;
	fichier << "---------- FEEDBACK END ----------";

	fichier.close();

	return 0;
}

int Lfsr::init(int size, char* init_registre, char* retroaction){
	this->size = size; //
	this->registre = convert_char_to_int32(init_registre,size);
	this->retroaction = convert_char_to_int32(retroaction,size);
	return 0;
}

int Lfsr::generate_bits(const int key_size){

register int i, j;
int key;
uint8_t exit_val;

	for(i = key_size-1; i >= 0; i--){
		//dernier bit du registre dans key
		exit_val = RDINT(this->registre,this->size-1);
		switch(exit_val){
			case 0 : WZINT(key,i); break;
			case 1 : WOINT(key,i); break;
		}

		//calcul de la nouvelle valeur à entrer dans le registre
		for(j = this->size-1; j > 0; j--){
			if(RDINT(this->retroaction,j) == 1)	exit_val ^= RDINT(this->registre,j-1);
		}

		//décalage du registre
		this->registre *= 2;

		//nouvelle valeur du registre
		//printf("NEW VAL %d\n",exit_val);
		switch(exit_val){
			case 0 : WZINT(this->registre,0); break;
			case 1 : WOINT(this->registre,0); break;
		}
		//this->display();
	}

	return key;
}

int Lfsr::encrypt(int data, int key){
	return data^key;
}

void Lfsr::encrypt_into_buffer(char* buffer, int pos, int size, int data, int key){

int i = 0, j = 0, limit = (pos+size);
int encrypted_data = data^key;

	//vérifier que les xor entre les bits soient bien de la pos 0 à size dans encrypted_data, et pas de 32 à 32-size...

	for(i = pos; i < limit; i++){
		switch(RDINT(encrypted_data,j)){
			case 0:
				buffer[i] = '0'; ++j; break;
			case 1: 
				buffer[i] = '1'; ++j; break;
		}
	}

}

void Lfsr::display(void) const{

register int i;

	printf("display lfsr :\n\tlfsr->size = %d\n",this->size);
	printf("\tlfsr->registre =    ");
	for(i = 0; i < this->size; i++){
		printf("%d",RDINT(this->registre,i));
	}
	printf("\n");

	printf("\tlfsr->retroaction = ");
	for(i = 0; i < this->size+1; i++){
		printf("%d",RDINT(this->retroaction,i));
	}
	printf("\n");
}

int Lfsr::getRegistre() const{	return this->registre;	}
int Lfsr::getRetroaction() const{	return this->retroaction;	}
int Lfsr::getSize() const{	return this->size;	}

Lfsr::~Lfsr(){
	//
}

/*
lfsr_t* init_lfsr_t(char* init, char* retroaction){

//lfsr_t *lfsr = (lfsr_t*)malloc(sizeof(lfsr_t));
lfsr_t *lfsr = CREATE(lfsr, lfsr_t, 1);

	lfsr->size = strlen(init);
	lfsr->registre = convert_char_to_int32(init);
	lfsr->retroaction = convert_char_to_int32(retroaction);

	return lfsr;

}


void display_lfsr_t(lfsr_t *lfsr){

register int i;

	printf("display lfsr :\n\tlfsr->size = %d\n",lfsr->size);
	printf("\tlfsr->registre =    ");
	for(i = 0; i < lfsr->size; i++){
		printf("%d",RDINT(lfsr->registre,i));
	}
	printf("\n");

	printf("\tlfsr->retroaction = ");
	for(i = 0; i < lfsr->size+1; i++){
		printf("%d",RDINT(lfsr->retroaction,i));
	}
	printf("\n");

}


int lfsr_t_generate_key(lfsr_t *lfsr, int key_size){

register int i, j;
int key;
uint8_t exit_val;

	for(i = key_size-1; i >= 0; i--){
		//dernier bit du registre dans key
		exit_val = RDINT(lfsr->registre,lfsr->size-1);
		switch(exit_val){
			case 0 : WZINT(key,i); break;
			case 1 : WOINT(key,i); break;
		}

		//calcul de la nouvelle valeur à entrer dans le registre
		for(j = lfsr->size-1; j > 0; j--){
			if(RDINT(lfsr->retroaction,j) == 1)	exit_val ^= RDINT(lfsr->registre,j-1);
		}

		//décalage du registre
		lfsr->registre *= 2;

		//nouvelle valeur du registre
		//printf("NEW VAL %d\n",exit_val);
		switch(exit_val){
			case 0 : WZINT(lfsr->registre,0); break;
			case 1 : WOINT(lfsr->registre,0); break;
		}
		//display_lfsr_t(lfsr);
	}

	return key;

}


int lfsr_t_encrypt(int data, int key){
	return data^key;
}
*/